/**
 *
 * @Project： Lqyd_Android
 * @Title：LogUtil
 * @Description：
 * @Author：wayne
 * @Date：2014年8月8日上午1:14:00
 *
 */
package logic.util.logutil;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import logic.constants.AppConfig;
import logic.util.FileUtil;
import logic.util.MultiCard;
import logic.util.SDcardUtil;
import logic.util.Util;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;

/**
 * 打印日志类<br>
 * 可在AndroidManifest.xml中的application节点下设置debug模式:
 * <code>android:debuggable="true"</code> 或者
 * <code>android:debuggable="false"</code>; <br>
 * 程序启动时需执行 <code>LogUtil.isApplicationDebug(this);</code>
 * 判断关联AndroidManifest.xml中的debug设置；<br>
 * 监听记录程序崩溃日志，在Activity的onCreate方法中执行： <code>LogUtil.onError(this);</code>
 * <p>
 * 所需权限：<br>
 * <code><uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /></code>
 * 
 * @公司 杭州龙骞科技有限公司
 */
public class LogUtil
{
	private static final int		file_max_size	= 1 * 1024 * 1024;																					// FIXME
	private static final String		dir				= Environment.getExternalStorageDirectory().getPath() + "/" + MultiCard.ECP_DIRECTORY_NAME + "log"; // FIXME
	private static boolean			isDebug			= true;																							// FIXME

	private static BufferedWriter	mBufferedWriter;

	private static final String		lz_tag			= "shmily480";
	private static final String		dzp_tag			= "daizhipeng";
	private static final String		lhh_tag			= "luhuhai";
	private static final String		fw_tag			= "wayne1929";
	private static final String		louis_tag		= "louis";
	private static final String		lh_tag			= "Liu";
	private static final String		why_tag			= "wendy";
	

	/**
	 * 判断关联AndroidManifest.xml中的debug设置;
	 * 
	 * @param context
	 * @return
	 */
	public static boolean isApplicationDebug(Context context) {
		try
		{
			PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
			int flags = packageInfo.applicationInfo.flags;
			int debug = (flags & ApplicationInfo.FLAG_DEBUGGABLE);
			if (debug != 0)
			{
				// development mode
				isDebug = true;
			}
			else
			{
				// release mode
				isDebug = false;
			}
		}
		catch (NameNotFoundException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return isDebug;
	}

	/**
	 * 写文件
	 */
	private static void writeLogFile(String tag, String msg) {
		if (AppConfig.isDebugMode())
		{
			if (mBufferedWriter == null && SDcardUtil.isSDCARDMounted())
			{
				try
				{
					File mFile = new File(new StringBuilder(SDcardUtil.getLogPath().getPath()).append("log").append("_")
									.append(new SimpleDateFormat("yyyyMMdd_HH").format(new Date())).append(".txt").toString());
					mBufferedWriter = new BufferedWriter(new FileWriter(mFile, true));
				}
				catch (IOException e)
				{
					e.printStackTrace();
					mBufferedWriter = null;
					return;
				}
			}

			SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss:SSS");
			String buffer = sdf.format(new Date()) + ": " + tag + ": " + msg + "\n";
			try
			{
				mBufferedWriter.append(buffer);
				mBufferedWriter.flush();
			}
			catch (Exception e)
			{
				endWriteFile();
			}
		}
	}

	/**
	 * 结束记录文件
	 */
	public static void endWriteFile() {
		if (mBufferedWriter != null)
		{
			try
			{
				mBufferedWriter.flush();
				mBufferedWriter.close();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			mBufferedWriter = null;
		}
	}

	/**
	 * 销毁
	 */
	public static void destroy() {
		endWriteFile();
	}

	public static void v(String tag, String msg) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.v(tag, buildMessage(msg));
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void v(String tag, String msg, Throwable thr) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.v(tag, buildMessage(msg), thr);
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void d(String tag, String msg) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.d(tag, buildMessage(msg));
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void d(String tag, String msg, Throwable thr) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.d(tag, buildMessage(msg), thr);
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void i(String tag, String msg) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.i(tag, buildMessage(msg));
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void i(String tag, String msg, Throwable thr) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.i(tag, buildMessage(msg), thr);
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void d_ZWT(String msg) {
		if (AppConfig.isDebugMode())
		{
			d("zwt", msg);
		}
	};
	public static void d_ZWT(int msg) {
		if (AppConfig.isDebugMode())
		{
			d("zwt", String.valueOf(msg));
		}
		
	};

	public static void w(String tag, String msg) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.w(tag, buildMessage(msg));
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void w(String tag, String msg, Throwable thr) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.w(tag, buildMessage(msg), thr);
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void w(String tag, Throwable thr) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.w(tag, buildMessage(""), thr);
		}
	}

	public static void e(String tag, String msg) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.e(tag, buildMessage(msg));
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	public static void e(String tag, String msg, Throwable thr) {
		if (AppConfig.isDebugMode())
		{
			android.util.Log.e(tag, buildMessage(msg), thr);
			//writeLogFile(tag, buildMessage(msg));
		}
	}

	private static String buildMessage(String msg) {
		StackTraceElement caller = new Throwable().fillInStackTrace().getStackTrace()[2];
		String className = caller.getClassName();
		String simpleClassName = className.substring(className.lastIndexOf(".") + 1);
		return new StringBuilder().append(simpleClassName).append(".").append(caller.getMethodName()).append("(").append(caller.getLineNumber()).append("):")
						.append(msg).toString();
	}

	/**
	 * 将以下代码放置程序的activity的onCreate方法中，即可在debug状态下将崩溃异常信息存放到该路径
	 * 
	 * @param mContext
	 */
	public static void onError(final Context mContext) {
		if (AppConfig.isDebugMode())
		{
			new Thread()
			{

				@Override
				public void run() {
					String str = catchLogError(mContext);
					if (!Util.isEmpty(str))
					{
						if (mContext.getPackageManager().checkPermission("android.permission.READ_LOGS", mContext.getPackageName()) != PackageManager.PERMISSION_GRANTED) { return; }
						BufferedWriter mBufferedWriter = null;
						try
						{
							File mFile = new File(new StringBuilder(SDcardUtil.getLogPath().getPath()).append("error_log").append("_")
											.append(new SimpleDateFormat("yyyyMMdd_HH").format(new Date())).append(".txt").toString());
							if (mFile.length() > file_max_size)
							{
								mFile.delete();
								mFile.createNewFile();
							}
							String time = ">>>>>>>>>>>>>>>>>> " + Util.getFormatTime("yyyy-MM-dd HH:mm:ss:SSS") + "\n";
							mBufferedWriter = new BufferedWriter(new FileWriter(mFile, true));
							mBufferedWriter.append(time);
							mBufferedWriter.append(str);
							mBufferedWriter.append("\n\n");
							mBufferedWriter.flush();
						}
						catch (IOException e)
						{
							e.printStackTrace();
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
						finally
						{
							if (mBufferedWriter != null)
							{
								try
								{
									mBufferedWriter.close();
									mBufferedWriter = null;
								}
								catch (IOException e)
								{
									e.printStackTrace();
								}
							}
						}
					}
				}

			}.start();
		}
	}

	/**
	 * 捕获异常信息
	 * 
	 * @param mContext
	 * @return
	 */
	private static String catchLogError(Context mContext) {
		String error = "";
		try
		{
			String packageName = mContext.getPackageName();
			String log = "";
			boolean ifOurs = false;
			boolean ifException = false;
			ArrayList<String> commandLine = new ArrayList<String>();
			commandLine.add("logcat");
			commandLine.add("-d");
			commandLine.add("-v");
			commandLine.add("raw");
			commandLine.add("-s");
			commandLine.add("AndroidRuntime:E");
			commandLine.add("-p");
			commandLine.add(packageName);
			Process process = Runtime.getRuntime().exec((String[]) commandLine.toArray(new String[commandLine.size()]));
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 1024);
			String line = bufferedReader.readLine();

			while (line != null)
			{
				if (line.indexOf("thread attach failed") < 0)
				{
					log = log + line + '\n';
				}
				if ((!ifException) && (line.toLowerCase().indexOf("exception") >= 0))
				{
					ifException = true;
				}
				if ((!ifOurs) && (line.indexOf(packageName) >= 0))
				{
					ifOurs = true;
				}
				line = bufferedReader.readLine();
			}

			if ((log.length() > 0) && (ifException) && (ifOurs))
			{
				error = log;
			}
			try
			{
				Runtime.getRuntime().exec("logcat -c");
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return error;
	}

	/**************************** 自定义部分 ***********************************/
	
	public static void packin(String msg){
		d("packin",msg);
	}
	
	public static void packout(String msg){
		d("packout",msg);
	}

	public static void Lz_d(String msg) {
		d(lz_tag, msg);
	}

	public static void Lz_e(String msg, Throwable tr) {
		e(lz_tag, msg, tr);
	}

	public static void lhh_d(String msg) {
		d(lhh_tag, msg);
	}

	public static void lhh_e(String msg, Throwable tr) {
		e(lhh_tag, msg, tr);
	}

	public static void dzp_d(String msg) {
		d(dzp_tag, msg);
	}

	public static void dzp_e(String msg, Throwable tr) {
		e(dzp_tag, msg, tr);
	}

	public static void fw_d(String msg) {
		d(fw_tag, msg);
	}

	public static void fw_e(String msg, Throwable tr) {
		e(fw_tag, msg, tr);
	}

	public static void louis_d(String msg) {
		d(louis_tag, msg);
	}

	public static void louis_e(String msg, Throwable tr) {
		e(louis_tag, msg, tr);
	}

	public static void Liu_d(String msg) {
		d(lh_tag, msg);
	}

	public static void Liu_e(String msg, Throwable tr) {
		e(lh_tag, msg, tr);
	}

	public static void Why_i(String msg) {
		//if(false)
		i(why_tag, msg);
	}

	public static void Why_e(String msg, Throwable tr) {
		e(why_tag, msg, tr);
	}
}
